//
// Created by dongbo on 11/11/18.
//

#ifndef PAXOS_role_MAIN_H
#define PAXOS_role_MAIN_H


#include <iostream>
#include <sstream>
#include <set>
#include <map>
#include <atomic>

#include "evpaxos.h"
#include "learner_xy.h"
#include "../job.h"
#include "../zmqpipe.h"
#include "../z_hglog.h"


struct ppax_cb {
    virtual void master_ischange() = 0;

};

class role_acceptor;

class role_proposer;

class role_learner : public role {
    struct client_value {
        int client_id;
        struct timeval t;
        size_t size;
        char value[1];
    };

public:
    role_learner(int _id,
                 role_acceptor *accp,
                 role_proposer *prop,
                 ppax_cb *_ppxcb,
                 struct evpaxos_config *_config);

    static void handle_sigint(int sig, short ev, void *arg);

    static void deliver(unsigned iid, char *value, size_t size, void *arg);

    void start_learner();

    void set_zpip(zmqpipe *_zpip_in, int zmqpip_num);

    virtual void set_masterid(int _id);

    virtual void set_lease_timep(int timep);

    virtual int get_masterid();

    virtual int get_lease_timep();

    virtual bool is_master(int _id);

    virtual void event_master_change();

    bool is_ok() { return ok; };
private:
    zmqpipe *zpip_in;
    int zmqpip_num;
private:
    std::atomic_bool ok = {false};
    role_proposer *rprop;
    role_acceptor *raccp;
    ppax_cb *ppxcb;
};


class role_acceptor : public role {

public:
    role_acceptor(ppax_cb *_ppxcb);

    static void handle_sigint(int sig, short ev, void *arg);

    void start_acceptor();

    virtual void set_masterid(int _id);

    virtual void set_lease_timep(int timep);

    virtual int get_masterid();

    virtual int get_lease_timep();

    virtual void event_master_change();

    virtual bool is_master(int _id);

private:
    ppax_cb *ppxcb;
};


class role_proposer : public role {

public:
    role_proposer(ppax_cb *_ppxcb);

    static void handle_sigint(int sig, short ev, void *arg);

    void start_proposer();

    virtual void set_masterid(int _id);

    virtual void set_lease_timep(int timep);

    virtual int get_masterid();

    virtual int get_lease_timep();

    virtual void event_master_change();

    virtual bool is_master(int _id);

private:
    ppax_cb *ppxcb;
};


#endif //PAXOS_role_MAIN_H
